import axios from "axios";
import type { AxiosInstance } from "axios";
import type { ZLRequestInterceptors, ZLRequestConfig } from "./type";

import { ElLoading } from "element-plus";
import { LoadingInstance } from "element-plus/lib/components/loading/src/loading.js";
import { useNavBarHooks } from "../../components/navBar/hooks";

const DEFAULT_LOADING = true;
const DEFAULT_LOADING_TARGET = "body";


// 函数返回唯一的请求key
// function getRequestKey(config: any) {
//   let { method, url, params, data } = config;
//   return [method, url, JSON.stringify(params), JSON.stringify(data)].join("&");
// }

// // 添加请求信息
// let pendingRequest = new Map();
// function addPendingRequest(config: any) {
//   let requestKey = getRequestKey(config);
//   config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
//     if (!pendingRequest.has(requestKey)) {
//       pendingRequest.set(requestKey, cancel);
//     }
//   });

class ZLRequest {
  instance: AxiosInstance;
  interceptors?: ZLRequestInterceptors;
  showLoading: boolean;
  loading?: LoadingInstance;

  constructor(config: ZLRequestConfig) {
    this.instance = axios.create(config);
    this.showLoading = config.showLoading ?? DEFAULT_LOADING;
    this.interceptors = config.interceptors;

    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptor,
      this.interceptors?.requestInterceptorCatch,
    );

    this.instance.interceptors.response.use(
      this.interceptors?.responseInterceptor,
      this.interceptors?.responseInterceptorCatch
    );

    //添加所有的实例都有的拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 开启加载前先移除当前多余的加载实例,避免出现叠加现象
        this.loading?.close();

        if (this.showLoading) {
          this.loading = ElLoading.service({
            lock: true,
            text: "正在拼命加载中......",
            background: "rgba(0,0,0,0.5)"
          });
        }
        return config;
      },
      (err) => {
        ElNotification({
          title: "错误",
          message: "网络错误!",
          type: "error"
        });
        return err;
      }
    );

    this.instance.interceptors.response.use(
      (res) => {
        //移除loading
        this.loading?.close();

        const data = res.data;
        if (!res.status) {
          return ElNotification({
            title: "错误",
            message: "服务器错误",
            type: "error"
          });
        }

        if (data.code != "200" || !data.code) {
          if (data.code === 401) {
            const { logout } = useNavBarHooks();
            // 401错误，清除token
            logout()
          } else {
            ElNotification({
              title: "错误",
              message: data.msg || "网络错误!",
              type: "error"
            });
          }
          return data
        } else {
          return data;
        }
      },
      (err) => {
        //移除loading
        this.loading?.close();
        if (err.response.code === 400) {
        }
        ElNotification({
          title: "错误",
          message: "网络错误!",
          type: "error"
        });
        return err;
      }
    );
  }

  request<T = any>(config: ZLRequestConfig<T>): Promise<T> {
    return new Promise((resolve) => {
      if (config.interceptors?.requestInterceptor) {
        config = config.interceptors.requestInterceptor(config);
      }

      if (config.showLoading === false) {
        this.showLoading = config.showLoading;
      }

      if (config.loadingTarget !== "body") {
        this.loadingTarget = config.loadingTarget;
      }

      this.instance
        .request<any, T>(config)
        .then((res) => {
          if (config.interceptors?.responseInterceptor) {
            res = config.interceptors.responseInterceptor(res);
          }
          //将showLoading设置为true，这样不会影响下一个请求
          this.showLoading = DEFAULT_LOADING;
          this.loadingTarget = DEFAULT_LOADING_TARGET;

          //将结果返回
          resolve(res);
        })
        .catch((err) => {
          //将showLoading设置为true，这样不会影响下一个请求
          this.showLoading = DEFAULT_LOADING;
          this.loadingTarget = DEFAULT_LOADING_TARGET;
          return err;
        });
    });
  }

  get<T = any>(config: ZLRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: "GET" });
  }
  post<T = any>(config: ZLRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: "POST" });
  }
  delete<T = any>(config: ZLRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: "DELETE" });
  }
  patch<T = any>(config: ZLRequestConfig<T>): Promise<T> {
    return this.request<T>({ ...config, method: "PATCH" });
  }
}

export default ZLRequest
